#include "interrupt.h"

static uint8_t _g_current = 0;                                // 中断计数
static void (*_g_methods[INTERRUPT_METHOD_SIZE])(void) = {0}; // 中断处理

/**
 * @name 中断处理
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
void INTERRUPT_TIM_IRQHandler(void) {
    uint8_t i = 0;
    // 中断就绪
    if (TIM_GetITStatus(INTERRUPT_TIM, TIM_IT_Update) != RESET) {
        // 中断处理
        while (i < _g_current)
            _g_methods[i++]();
        // 清除标志
        TIM_ClearITPendingBit(INTERRUPT_TIM, TIM_IT_Update);
    }
}

/**
 * @name 中断初始化
 * @description
 * @function
 * @returns {*}
 * @requires []
 */
void interrupt_init(void) {
    NVIC_InitTypeDef NVIC_InitStruct = {0};
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct = {0};
    // 使能时钟
    INTERRUPT_RCC_APBPeriphClockCmd;
    // 配置时钟
    TIM_TimeBaseInitStruct.TIM_Prescaler = INTERRUPT_TIM_Prescaler;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = INTERRUPT_TIM_Period;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    // 初始时钟
    TIM_TimeBaseInit(INTERRUPT_TIM, &TIM_TimeBaseInitStruct);
    // 使能中断
    TIM_ITConfig(INTERRUPT_TIM, TIM_IT_Update, ENABLE);
    // 优先分组
    SYS_NVIC_PriorityGroupConfig;
    // 配置中断
    NVIC_InitStruct.NVIC_IRQChannel = INTERRUPT_TIM_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = INTERRUPT_NVIC_IRQChannelPreemptionPriority;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = INTERRUPT_NVIC_IRQChannelSubPriority;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    // 初始中断
    NVIC_Init(&NVIC_InitStruct);
    // 使能定时
    TIM_Cmd(INTERRUPT_TIM, ENABLE);
}

/**
 * @name 中断注册
 * @description
 * @function
 * @param {void (*method)(void)} 中断函数
 * @returns {uint8_t} 0: 成功, 1: 注册已满, 2: 已经注册
 * @requires []
 */
uint8_t interrupt_register(void (*method)(void)) {
    uint8_t i = 0;
    // 注册已满
    if (_g_current >= INTERRUPT_METHOD_SIZE)
        return 1;
    // 已经注册
    while (i < _g_current)
        if (_g_methods[i++] == method)
            return 2;
    // 注册方法
    _g_methods[_g_current++] = method;
    // 返回成功
    return 0;
}

/**
 * @name 中断注销
 * @description
 * @function
 * @param {void (*method)(void)} 中断函数
 * @returns {uint8_t} 0: 成功, 1: 注销失败
 * @requires []
 */
uint8_t interrupt_unregister(void (*method)(void)) {
    uint8_t i = 0;
    // 查找注销
    while (i < _g_current)
        if (_g_methods[i++] == method) {
            while (i < _g_current)
                _g_methods[i - 1] = _g_methods[i];
            --_g_current;
            return 0;
        }
    return 1;
}
